/*
 * Copyright (c) 2022-2023 cetcclout Co., Ltd All rights reserved.
 * Sensor Adapter is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package com.cetccloud.cimp.adapter.handler.hj212;

import cn.hutool.core.util.ObjectUtil;
import com.cetccloud.cimp.adapter.cache.ClientDeviceCache;
import com.cetccloud.cimp.adapter.datasource.redis.RedisService;
import com.cetccloud.cimp.adapter.datasource.redis.impl.RedisServiceImpl;
import com.cetccloud.cimp.adapter.handler.DataContextValue;
import com.cetccloud.cimp.adapter.handler.abstracts.AbstractAuthHandler;
import com.cetccloud.cimp.adapter.handler.hj212.parse.EnvHJ212Parse;
import com.cetccloud.cimp.adapter.server.mqtt.publish.MqttDtuIdClientService;
import com.cetccloud.cimp.common.util.SensorStringUtils;
import com.xy.format.hbt212.model.standard.Data;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.nio.Buffer;

/**
 * @author
 * @apiNote 设备注册校验
 * @date 2023/3/3 19:20
 */
@Component("hj212AuthHandler")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class HJ212AuthHandler extends AbstractAuthHandler {

    private static final InternalLogger logger = InternalLoggerFactory.getInstance(HJ212AuthHandler.class);

    @Autowired
    private RedisService redisService;

    @Autowired
    private RedisServiceImpl redisServiceImpl;
    @Autowired
    private MqttDtuIdClientService mqttDtuIdClientService;

    /**
     * 设备数据解析
     */
    @Override
    public String auth(Buffer buffer, Object context) {
        String receiveData = new String((byte[]) buffer.array()).trim();

        String deviceId = null;
        if (SensorStringUtils.startsWith(receiveData, "##")){
            try {
                // HJ212 data package
                Data data = EnvHJ212Parse.parseHJ212Data(receiveData + "\r\n");
                createTcpConn((ChannelHandlerContext) context, data.getMn());
                deviceId = data.getMn();
            } catch (Exception e) {
                ((ChannelHandlerContext) context).channel().close();
                e.printStackTrace();
            }
        }

        return deviceId;
    }


    /**
     * 设备注册信息验证
     */
    private boolean createTcpConn(ChannelHandlerContext context, String deviceId) {

        ChannelHandlerContext ctx = context;
        // exist deviceId
        String memoryDeviceId = ClientDeviceCache.getDtuId(ctx.channel()).trim();

        if(SensorStringUtils.isEmpty(memoryDeviceId)){
            // 判断监控仪是否合法存在
            if(redisService.hasKey(String.format(RedisServiceImpl.JR_DEVICE_MODEL_KEY, deviceId))
                    && ObjectUtil.isNotEmpty(redisServiceImpl.getModelByDevice(deviceId))){
                ClientDeviceCache.addChannel(deviceId, ctx.channel());
                //创建mqtt链接
                mqttDtuIdClientService.MakeClient(deviceId);
                logger.info("成功初始化，注册链接 ： " + deviceId);
                //非设备正常连接 不记录
                redisService.sSet(DataContextValue.DTU_STATUS_KEY, deviceId);
            }else{
                logger.error("监控仪信息非法，请先在平台注册监控仪信息！");
                ctx.channel().close();
            }
            logger.info("存储设备和通信信道：{}", ClientDeviceCache.getMap());
            return false;
        }else {
            return true;
        }
    }

    /**
     * 签名以供设备识别
     */
    @Override
    public Buffer sign(Buffer buffer, String dtuId) {
        //todo 签名加密
        logger.info("数据出站的签名！！！");
        return buffer;
    }
}
